/**---------------------------------------------------History---------------------------------------------------------*/
 /* <p>Title: workflowscript</p>
 * <p>Description: IBatch Workflow Editor Script Doc </p>
 * <p>Copyright: Baosight Software LTD.co Copyright (c) 2002</p>
 * <p>Company: IBatch Software</p>
 * @author 汪国岩
 * @version 1.0
 * <pre>Histroy:
 * 2016-9-26
 *</pre>
/*--------------------------------------------------------------------------------------------------------------------*/
/**
 * Edited by 汪国岩 on 2016/12/29.
 * Event: Join the program into the ibcp-client, delete some useless JS documents.
 */
/*--------------------------------------------------------------------------------------------------------------------*/




// JavaScript Document
/*---------------------------------------------------全局变量----------------------------------------------------------*/
var canvas;															//定义画布
var signal;															//绘制连接线信标,加载默认为false,当触发绘制连接线按钮时为true
var started;														//绘制矢量连接线信标
var lines = [];														//存储所有画布上的连接线
var objs = [];														//存储全局元素（线条除外）
var connectors = [];												//存储所有画布上的矢量连接线
var Id = 1;															//连接线和元素识别的id
var processline;													//绘制连接线动态过程线段添删控制名
document.onkeydown = keyDown;										//设置键盘监听
document.onkeyup = keyUp;											//键盘按键抬起事件
document.onmousewheel = mouseWheel;									//注册鼠标滚轮事件
var helppoint;														//连接线提示点
var zoom = 1;														//canvas缩放系数
var txt;															//XML时时存储字符串
var configTxt;														//记录XML字符串存储
var configStore = [];												//时时记录配置
var xmlDoc;															//XML对象
var revocation = false;												//撤销动作新标
var workFlowId = GetUrlParam("workFlowId");							//程序id
var FontSize = 14;													//显示字体大小
var PageName;														//当前页面名称
var ActiveId;														//当前获取待操作的节点id（新建和选中）
var ActiveConnector;												//当前获取等待操作的连接线
var Edit = 1;														//当前处于编辑状态（1 || 0）
var stepAddDivIndex;												//步骤选择页面

var workFlowEditUrl = serverPath + "craftProcess/updateCraftProcessResource ";		//编辑工作流服务器地址
var workFlowCheckUrl = serverPath + "craftProcess/findCraftProcessDetail";			//修改工作流服务器地址
/*---------------------------------------------------------------------------------------------------------------------*/

//初始化编辑器页面
function initPage(opera) {
	try{
		PageName = opera;											//当前页面名称
		signal = false;
		canvas = new fabric.Canvas('canvas');						//选择画布
		canvas.backgroundColor = '#FFF';							//设置画布背景色
		initMouseEvent(opera);										//初始化鼠标事件
		initHelpPoint();											//初始化链接提示点
		clearInstallPage();											//清除属性面板信息
		setEditStateByType("clear");								//隐藏属性面板
		getXMLFromServer();											//读取服务器配置生成当前程序

		if (opera == 'check') {
			fixAllTarget();
		}
		if (opera == 'edit') {
			Start();
			End();
		}
		reLoadTagsCollection();										//刷新节点集合选项
		initCurrentTargetSelector();								//初始化节点集合选择框
	}
	catch(e) {
		alert(e);
	}
}


/*---菜单功能按钮---*/
//“新建”按钮动作
function Create() {
	'use strict';
	var con = confirm('是否放弃目前工作？');
	if (con == true) {
		window.location.href=window.location.href;
		window.location.reload;
	}
	else if (con == false) {
		return;
	}
}

//记录配置按钮
function ConfigInfo() {
	'use strict';
	try{
		configInfo(true);
		configTxt = txt;
	}
	catch(e) {
		alert(e);
	}
}

//加载配置按钮
function LoadConfigInfo() {
	'use strict';
	try{
		canvas.clear();
		ClearPage(function(){
			getXMLFromServer();												//读取服务器配置生成当前程序
		});
	}
	catch(e) {
		alert('配置信息未记录！');
	}
}

//清空工作台
function ClearPage(okCallback) {
	'use strict';
	try{
		canvas.clear();
		connectors = [];
		objs = [];
		clearInstallPage();
		clearSelectOptions("Current_Target");
		if(okCallback){
			okCallback();
		}else{
			Start();
			End();
		}
	}
	catch(e) {
		alert(e);
	}
}

//刷新页面
function RefreshPage(){
	'use strict';
	try{
		var newTxt = txt;
		ClearPage(function(){
			loadConfigInfo(newTxt);				//加载
		});

	}
	catch(e){
		alert(e);
	}
}

/*-------------------------------------------------------工具按钮功能块-----------------------------------------------*/
//绘制连接线
function Connect(sig) {
	'use strict';
	//判断是否开始（防止Ctrl和直接点击按钮的冲突）
	if(sig == null){
		started = !started;
	}
	else{
		started = sig;
	}
	setConnectorsSelectable(!started);
	setButtonSelected($('button[onClick="Connect()"]'),started);
	//当前所有节点不可移动或缩放
	for (var i in objs) {
		objs[i].set({
			lockMovementX:started,
			lockMovementY:started,
			lockScalingX:started,
			lockScalingY:started
		});
	}
	if (started == false) {
		hideHelpPoint();
	}
}

//判断某点位于元素的十字线四个点的哪一个点，并返回该点坐标
//Array whitchPointInObject(Array,object)
function whitchPointInObject(Point,Obj) {
	'use strict';
	var distance = 20;
	var left = [];
	var top = [];
	var right = [];
	var bottom = [];
	left = GetPointFromObj(Obj,'L');
	top = GetPointFromObj(Obj,'T');
	right = GetPointFromObj(Obj,'R');
	bottom = GetPointFromObj(Obj,'B');

	if (PointBeside(Point,left,distance)) {
		return(left);
	}
	if (PointBeside(Point,top,distance)) {
		return(top);
	}
	if (PointBeside(Point,right,distance)) {
		return(right);
	}
	if (PointBeside(Point,bottom,distance)) {
		return(bottom);
	}
}

//判断鼠标当前坐标位于元素的十字线四个点的哪一个点，返回点的位置名称
//Str whitchPointInObjectStr(Array, object)
function whitchPointInObjectStr(Point,Obj) {
	'use strict';
	var distance = 20;
	var left = [];
	var top = [];
	var right = [];
	var bottom = [];
	left = GetPointFromObj(Obj,'L');
	top = GetPointFromObj(Obj,'T');
	right = GetPointFromObj(Obj,'R');
	bottom = GetPointFromObj(Obj,'B');

	if (PointBeside(Point,left,distance)) {
		return('L');
	}
	if (PointBeside(Point,top,distance)) {
		return('T');
	}
	if (PointBeside(Point,right,distance)) {
		return('R');
	}
	if (PointBeside(Point,bottom,distance)) {
		return('B');
	}
}

//判断A点是否在B指定范围内
//Boolean PointBeside(array,array,num-范围距离)
function PointBeside(PointA, PointB, distance) {
	'use strict';
	var Bx1 = PointB[0] - distance;
	var Bx2 = PointB[0] + distance;
	var By1 = PointB[1] - distance;
	var By2 = PointB[1] + distance;
	if (PointA[0] > Bx1 && PointA[0] < Bx2 && PointA[1] > By1 && PointA[1] < By2) {
		return (true);
	}
	else {
		return (false);
	}
}

////向量箭头连接线设置
//function VectorConnect(x1,y1,x2,y2){
//	'use strict'
//	var Vectors = [];
//	Vectors[0] = new fabric.Line([x1,y1,x2,y2], {
//		stroke: 'black',
//      	strokeWidth: 1,
//      	selectable: true
//	});
//	var h = Math.sqrt(27);
//	
//	//根据两点所在位置获得箭头部位旋转角度
//	var ang;									//角度值
//	var Dvalue = Math.abs(x2 - x1);				//横坐标差值
//	var distance = Distance(x1,y1,x2,y2);		//线段距离
//	var division = ((Dvalue * 10000) / (distance * 10000));
//	var pi = ((180 * 10000) / (Math.PI * 10000));
//	//相对于终点，起点在第一象限
//	if(x2 >= x1 && y2 >= y1){
//		ang = Math.acos(division) * pi + 90; 
//	}
//	//起点在第二象限
//	if(x2 < x1 && y2 >= y1){
//		ang = Math.asin(division) * pi + 180;	
//	}
//	//起点在第三象限
//	if(x2 < x1 && y2 < y1){
//		ang = Math.acos(division) * pi + 270;
//	}
//	//起点在第四象限
//	if(x2 >= x1 && y2 < y1){
//		ang = Math.asin(division) * pi;	
//	}
//	
//	Vectors[1] = new fabric.Triangle({
//		height:h,
//		width:6,
//		fill:'black',
//		angle:ang,
//		originX:'center'
//	});
//	var po = new fabric.Point(x2,y2);
//	Vectors[1].setPositionByOrigin(po, 'center', 'top');
//	var V = new fabric.Group(Vectors,{
//		lockScalingFlip:true,
//		lockScalingY:true,
//		lockScalingX:true,
//		hasRotatingPoint:false,
//		lockUniScaling:true,
//		selectable: false,
//		hasControls:false,
//		evented:false
//	});
//	canvas.add(V);
//	canvas.sendToBack(V);
//	vectors.push(V);
//}


//判断指定点是否在指定Object内
//Boolearn PointInObject(number,number,obj)
function PointInObject(x,y,target) {
	'use strict'
	var leftSide = target.get('left');
	var topSide = target.get('top');
	var rightSide = target.get('left') + target.getWidth();
	var bottomSide = target.get('top') + target.getHeight();
	if ( x >= leftSide && x <= rightSide && y >= topSide && y <= bottomSide) {
		return true;
	}
	else {
		return false;
	}
}

//获取Object的border指定关键点（线条类除外）
//参数说明：L:left, B:bottom, R:right, T:Top, LT:left&top, LB:left&bottom, RB:right&bottom, RT:right&top, C:Center
//Array(x,y) GetPointFromObj(obj,string)
function GetPointFromObj(target,point) {
	'use strict';
	var co = [];
	co[0] = target.get('left');
	co[1] = co[0] + (target.getWidth() / 2);
	co[2] = co[0] + target.getWidth();
	co[3] = target.get('top');
	co[4] = co[3] + (target.getHeight() / 2);
	co[5] = co[3] + target.getHeight();
	if (point == 'L') {
		return([co[0],co[4]]);
	}
	else if (point == 'B') {
		return([co[1],co[5]]);
	}
	else if (point == 'R') {
		return([co[2],co[4]]);
	}
	else if (point == 'T') {
		return([co[1],co[3]]);
	}
	else if (point == 'LT') {
		return([co[0],co[3]]);
	}
	else if (point == 'LB') {
		return([co[0],co[5]]);
	}
	else if (point == 'RB') {
		return([co[2],co[5]]);
	}
	else if (point == 'RT') {
		return([co[2],co[3]]);
	}
	else if (point == 'C') {
		return([co[1],co[4]]);
	}
}





/*------------------------------------------------------节点、连接线绘制功能块-------------------------------------------*/
//绘制矩形按钮
function Rectangle() {
	'use strict';
	ActiveId = null;
	showStepSelect();			//弹出步骤选择
}

//绘制矩形节点
function drawRectangleCmd() {
	'use strict';
	var Task = [];
	//底层矩形样式
	Task[0] = new fabric.Rect({
		left:50,
		top:50,
		height:80,
		width:160,
		stroke:'#0000CC',
		strokeWidth:0.5,
		fill:'#3868A3'
	});
	//梯形高光效果
	Task[1] = new fabric.Path('M 51 50 L 209 50 L 205 55 L 55 55 z',{
		stroke:'#4485D5'
	});
	Task[1].setGradient('fill',{
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:4,
		colorStops:{
			0:'#366DB1',
			0.5:'#FFFFFF',
			1:'#4485D5',
		}
	});
	//第二层矩形样式
	Task[2] = new fabric.Rect({
		left:55,
		top:55,
		height:70,
		width:150,
	});
	Task[2].setGradient('fill',{
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:80,
		colorStops:{
			0:'#4485D5',
			1:'#366DB1'
		}
	});

	Task[3] = new fabric.Text('',{
		left:65,
		top:65,
		fontSize: 12,
		fontFamily: '宋体',
		textAlign:'center'
	});
	var task = new fabric.Group(Task);
	task.set({
		hasBorders:false,							//不显示控制器边框
		hasControls:false,							//不显示控制器
		lockScalingFlip:true,						//禁止翻转
		id:Id,
		objType:'Task'
	});
	ActiveId = task.id;
	task.setControlVisible('mtr',false);			//隐藏旋转控制器
	canvas.add(task);
	objs.push(task);
	canvas.renderAll();
	Id += 1;
	configOnTime();									//记录配置
	reLoadTagsCollection();
}

//绘制开始标记
function Start() {
	'use strict';
	if(checkUpTargetByType('Start')) return;
	var StartTag = [];
	StartTag[0] = new fabric.Rect({
		left:50,
		top:50,
		width:150,
		height:50,
		rx:25,
		ry:25,
	});
	StartTag[0].setGradient('fill', {
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:15,
		colorStops:{
			0:'#e5ff88',
			1:'#7b9942'
		}
	});

	//上层图形
	StartTag[1] = new fabric.Rect({
		left:55,
		top:55,
		height:40,
		width:140,
		rx:20,
		ry:20
	});
	StartTag[1].setGradient('fill',{
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:40,
		colorStops:{
			0:'#a5cd4e',
			1:'#8aac40'
		}
	});

	StartTag[2] = new fabric.Text('开始', {
		left:65,
		top:72,
		fontSize: FontSize,
		fontFamily: '宋体',
		textAlign:'center'
	});

	var startTag = new fabric.Group(StartTag);
	startTag.set({
		id:0,
		objType:"Start",
		stepname:"开始",
		hasBorders:false,							//不显示控制器边框
		hasControls:false,							//不显示控制器
		lockScalingFlip: true
		
	});
	startTag.setControlVisible('mtr',false);
	canvas.add(startTag);
	objs.push(startTag);
	centerTextForTarget(startTag);				//文字居中对齐
	configOnTime();			//记录配置
}


//绘制结束标记
function End() {
	if(checkUpTargetByType('End')) return;
	var EndTag = [];
	EndTag[0] = new fabric.Rect({
		left:50,
		top:50,
		width:150,
		height:50,
		rx:25,
		ry:25,
	});
	EndTag[0].setGradient('fill', {
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:15,
		colorStops:{
			0:'#e5ff88',
			1:'#7b9942'
		}
	});

	//上层图形
	EndTag[1] = new fabric.Rect({
		left:55,
		top:55,
		height:40,
		width:140,
		rx:20,
		ry:20
	});
	EndTag[1].setGradient('fill',{
		type:'linear',
		x1:100,
		y1:0,
		x2:100,
		y2:40,
		colorStops:{
			0:'#a5cd4e',
			1:'#8aac40'
		}
	});
	EndTag[2] = new fabric.Text('结束', {
		left:65,
		top:72,
		fontSize: FontSize,
		fontFamily: '宋体',
		textAlign:'center'
	});

	var circle = new fabric.Group(EndTag);
	circle.set({
		hasBorders:false,							//不显示控制器边框
		hasControls:false,							//不显示控制器
		lockScalingFlip:true,
		id:99999999,
		objType:'End',
		stepname:"结束"
	});
	circle.setControlVisible('mtr', false);
	canvas.add(circle);
	objs.push(circle);
	centerTextForTarget(circle);					//文字居中对齐
	configOnTime();				//记录配置
}

//绘制菱形按钮
function Diamond(){
	'use strict';
	drawDiamondCmd();			//绘制菱形
}

//绘制菱形方法
function drawDiamondCmd(){
	'use strict';
	var rects = [];
	//底层菱形
	rects[0] = new fabric.Rect({
		left:50,
		top:50,
		width:90,
		height:90,
		angle:45
	});
	var dis = getDistance(50, 50, 140, 140) / 2;
	//上层菱形
	rects[1] = new fabric.Rect({
		left:50,
		top:50,
		width:75,
		height:75,
		angle:45,
		fill:'red'
	});
	var po = new fabric.Point(50, 50 + dis);
	//两层菱形位置及样式渲染
	rects[1].setPositionByOrigin(po, 'center', 'center');
	rects[0].setGradient('fill', {
		type:'linear',
		x1:30,
		y1:30,
		x2:60,
		y2:60,
		colorStops:{
			0:'#db4b48',
			1:'#a23533'
		}
	});
	rects[1].setGradient('fill', {
		type:'linear',
		x1:30,
		y1:30,
		x2:60,
		y2:60,
		colorStops:{
			0:'#d64440',
			1:'#b13834'
		}
	});
	rects[2] = new fabric.Text('', {
		left:25,
		top:90,
		fontSize: 12,
		fontFamily: '宋体',
		textAlign:'center'
	});
	var Gate = new fabric.Group(rects);
	Gate.set({
		hasBorders:false,							//不显示控制器边框
		hasControls:false,							//不显示控制器
		lockScalingFlip:true,
		id:Id,
		objType:'Gate'
	});
	ActiveId = Gate.id;
	Gate.setScaleY(0.7);
	Gate.setControlVisible('mtr', false);
	canvas.add(Gate);
	objs.push(Gate);
	Id += 1;
	configOnTime();                      	//记录配置
	reLoadTagsCollection();
}
/*---------------------------------------------------------------------------------------------------------------------*/





//将元素发送到最顶端
function Shift(){
	'use strict';
	var activeObject = canvas.getActiveObject();
	if (activeObject)
	{
		canvas.bringToFront(activeObject);
	}
}

//删除元素按钮
function Delete(){
	'use strict';
	var activeObject = canvas.getActiveObject() || ActiveConnector;								//选取当前活动的object
	var numbers = [];																			//待删除的连接线序数
	if (activeObject.objType != "Start" || "End") {
		canvas.remove(activeObject);
		//判断为节点元素
		if (activeObject.objType == "Gate" || "Task") {
			for (var i in connectors) {
				if (connectors[i].endId == activeObject.id || connectors[i].headId == activeObject.id) {
					numbers.push(i);															//取出与该节点相连的连接线序数
					canvas.remove(connectors[i]);												//删除与该节点相连的连接线
				}
			}
			for (var i = numbers.length - 1; i >= 0; i--) {
				connectors.splice(numbers[i],1);												//在connectors删除与该节点有关的项
			}
			for (var i in objs) {
				if (objs[i].id == activeObject.id) {
					objs.splice(i,1);															//在objs中删除对应的项
				}
			}
		}
		//判断为连接线元素
		if (activeObject.objType == "Connector") {
			for(var i in connectors){
				if(	connectors[i] == activeObject){
					connectors.splice(i,1);
				}
			}
		}
		reLoadTagsCollection();																	//刷新节点集合
	}
}

//生成两个节点之间最短路径连接方案
function getOptimalConnection(starttarget, endtarget){
	'use strict';
	var startPo;
	var endpo;
	var center1 = new KeyPoint(GetPointFromObj(starttarget, 'C')[0], GetPointFromObj(starttarget, 'C')[1], '');		//起始节点中点
	var center2 = new KeyPoint(GetPointFromObj(endtarget, 'C')[0], GetPointFromObj(endtarget, 'C')[1], '');			//尾节点中点
	if (Math.abs(center2.y - center1.y) > Math.abs(center2.x - center1.x)){
		if(center2.y > center1.y){
			startPo = new KeyPoint(GetPointFromObj(starttarget, 'B')[0], GetPointFromObj(starttarget, 'B')[1], 'B');
		}
		if(center2.y < center1.y){
			startPo = new KeyPoint(GetPointFromObj(starttarget, 'T')[0], GetPointFromObj(starttarget, 'T')[1], 'T');
		}
	}
	if (Math.abs(center2.x - center1.x) > Math.abs(center2.y - center1.y)){
		if(center2.x < center1.x){
			startPo = new KeyPoint(GetPointFromObj(starttarget, 'L')[0], GetPointFromObj(starttarget, 'L')[1], 'L');
		}
		if(center2.x > center1.x){
			startPo = new KeyPoint(GetPointFromObj(starttarget, 'R')[0], GetPointFromObj(starttarget, 'R')[1], 'R');
		}
	}
	endpo = getOptimalPoint(startPo, endtarget);
	return([startPo, endPo]);
}

//获取一个点与一个节点中最近的连接点
function getOptimalPoint(po, target){
	'use strict';
	var pos = [];
	pos = getConsFromTarget(target);				//取出节点的四个连接点
	var result = compareDistance(pos[0], pos[1], pos[2], pos[3], po);
	return(result);
}

//获取一个节点的四个连接点
//Array(left, top, right, bottom)
function getConsFromTarget(target){
	'use strict';
	var leftcon = new KeyPoint(GetPointFromObj(target, 'L')[0], GetPointFromObj(target, 'L')[1], 'L');
	var topcon = new KeyPoint(GetPointFromObj(target, 'T')[0], GetPointFromObj(target, 'T')[1], 'T');
	var rightcon = new KeyPoint(GetPointFromObj(target, 'R')[0], GetPointFromObj(target, 'R')[1], 'R');
	var bottomcon = new KeyPoint(GetPointFromObj(target, 'B')[0], GetPointFromObj(target, 'B')[1], 'B');
	return([leftcon, topcon, rightcon, bottomcon]);
}

//比较四个点到定点之间的距离,返回最小值点坐标
function compareDistance(po1, po2, po3, po4, potag) {
	'use strict';
	var d1 = getDistance(po1, potag);
	var d2 = getDistance(po2, potag);
	var d3 = getDistance(po3, potag);
	var d4 = getDistance(po4, potag);
	var mi = Math.min(d1, d2, d3, d4);
	if (mi == d1) {
		return(po1);
	}
	else if (mi == d2) {
		return(po2);
	}
	else if (mi == d3) {
		return(po3);
	}
	else if (mi == d4) {
		return(po4);
	}
}

//计算两点之间的距离
function getDistance(po1, po2) {
	'use strict';
	var a1 = Math.pow(Math.abs(po1.x - po2.x), 2);
	var a2 = Math.pow(Math.abs(po1.y - po2.y), 2);
	var a3 = a1 + a2;
	return(Math.sqrt(a3));
}

//定义鼠标事件集
function initMouseEvent(operate) {
	'use strict';
	var StartPoint;					//起点坐标点
	var EndPoint;					//终点坐标点
	var ProcessPoint;				//链接过程提示点
	var process = false;			//连接线过程信标
	var ending = false;				//结束连接线绘制信标
	var starttarget;				//起始节点元素

	//鼠标按下时
	canvas.on('mouse:down', function(o) {
		/*手动绘制连接线起点部分*/
		if (started) {
			//取得当前活动元素
			var target = canvas.getActiveObject();
			starttarget = target;
			if (target) {
				/*鼠标当前坐标*/
				var p = canvas.getPointer(o.e);
				var po = [];
				po[0] = p.x;
				po[1] = p.y;
				var position = whitchPointInObjectStr(po,target);
				var point = [];
				point = whitchPointInObject(po,target);
				if (point) {
					//将当前点击的元素指定起始点坐标作为起点对象存入
					StartPoint = new KeyPoint(point[0], point[1], position);
					started = false;				//结束起点过程
					process = true;					//开始过程连接线绘制
					ending = true;					//开始连接线终点过程
					//定义过程提示线终点，绘制过程提示线
					var p = new KeyPoint(point[0] + 1, point[1] + 1, '');
					drawProcessLine(StartPoint, StartPoint);
				}
				/*鼠标获取到可选元素但没有在连接点上*/
				else {
					return;
				}
			}
			/*鼠标点击没有在可选元素内，结束本次绘制*/
			else {
				return;
			}
		}
	});

	//鼠标移动
	canvas.on('mouse:move',function(o) {
		/*绘制连接线过程（动态线提示）*/
		if (process) {
			var p = canvas.getPointer(o.e);
			ProcessPoint = new KeyPoint(p.x, p.y, 'process');
			processline.set({
				x1:StartPoint.x,
				y1:StartPoint.y,
				x2:ProcessPoint.x,
				y2:ProcessPoint.y
			});
			canvas.renderAll();
		}

		/*提示连接点*/
		if (started == true || process == true) {
			var p = canvas.getPointer(o.e);
			showConnectHelpPoint(p);
		}
	});

	//鼠标抬起
	canvas.on('mouse:up',function(o) {
		/*手动绘制连接线终点部分*/
		if(ending){
			var id;
			var p = canvas.getPointer(o.e);
			var target = canvas.getActiveObject();
			var po = [];
			po[0] = p.x;
			po[1] = p.y;
			//遍历到当前鼠标坐标下的元素，获取指定点位置，存入终点对象
			for (var i in objs) {
				//如果鼠标当前下有可选元素
				if (PointInObject(p.x, p.y, objs[i])) {
					if (objs[i] == starttarget) {
						StartPoint = EndPoint = null;
						canvas.remove(processline);
						return;
					}
					id = objs[i].id;
					var position = whitchPointInObjectStr(po, objs[i]);
					var point = [];
					point = whitchPointInObject(po, objs[i]);
					//结束时取到终点坐标
					if (point) {
						EndPoint = new KeyPoint(point[0],point[1],position);
						hideHelpPoint();													//隐藏连接提示点
						process = false;
						ending = false;
						started = true;
					}
					//在元素内，但没有对应到点
					else {
						StartPoint = EndPoint = null;
						process = ending = false;
						canvas.remove(processline);
						hideHelpPoint();													//隐藏连接提示点
						started = true;
						return;
					}
				}
			}
			//鼠标抬起时获取到终点坐标
			if (EndPoint) {
				var keypoints = [];
				keypoints = getKeyPoints(StartPoint,EndPoint);
				var connector = strokeConnector(keypoints);
				connector.set({
					startPo:StartPoint.position,									//连接线起点坐标相对元素位置
					endPo:EndPoint.position,										//连接线终点坐标相对元素位置
					headId:target.id,												//连接线起点连接元素id
					endId:id														//连接线终点连接元素id
				});
				canvas.add(connector);												//绘制连接线
				connectors.push(connector);											//储存连接线
				canvas.sendToBack(connector);										//将连接线放在canvas堆栈最底层
				setConnectorsSelectable(false);										//连接线不可选(fabric选中效果过滤)
				EndPoint = StartPoint = null;
				canvas.remove(processline);											//移除动态连接线
				hideHelpPoint();													//隐藏提示点
				process = ending = false;
				started = true;
				reLoadTagsCollection();												//刷新节点集合
			}
			//鼠标抬起时没有获取到终点坐标
			else {
				canvas.remove(processline);
				StartPoint = EndPoint = null;
				hideHelpPoint();
				process = ending = false;
				started = true;
				return;
			}
		}
	});

	//拖动元素
	canvas.on('object:moving', function(e) {
		var p = e.target;
		var po = [];
		var e = event || window.event;
		var x = e.clientX + 10;
		var y = e.clientY - 40;

		//刷新节点以及连接线
		arrangeTarget(p);
		canvas.renderAll();
		reDrawConnector(p);
		freshCanvas();
	});

	//缩放元素
	canvas.on('object:scaling',function(e) {
		var p = e.target;
		reDrawConnector(p);
	});

	//元素被选中
	canvas.on('object:selected',function(e) {
		var p = e.target;
		var po = [];
		var e = event || window.event;
		var x = e.clientX + 10;
		var y = e.clientY - 40;

		//清除属性面板
		clearInstallPage();

		//清除选择状态
		selectCleared();

		//显示属性信息
		showInfo(p);

		//节点集合中显示当前节点
		showCurrentTatgetSelect(p);

		//设置连接线选中状态(样式)
		if (p.objType == "Connector") {
			setConnectorSelected(p);
		}

		//选中判断项或步骤时将全局ActiveId替换为当前id
		if (p.objType == "Gate" || "Task") {
			setObjectSelected(p);
			ActiveId = p.id;
		}
	});

	//清除选择状态
	canvas.on('selection:cleared', function(e) {
		clearInstallPage();									//清除属性面板信息
		setEditStateByType("clear");						//隐藏属性面板
		selectCleared();									//清除选中状态
	});

	//元素属性改变
	canvas.on('object:modified', function(e) {
		configOnTime();
	});
}

//通过鼠标滚轮缩放canvas
function mouseWheel(e)
{
	var point = new fabric.Point(0,0);
	var wheel = e.wheelDelta/120;
	//Alt键辅助
	if (e.altKey) {
		e.preventDefault();
		//滚轮向上滑动
		if (wheel>0) {
			if (zoom >= 1.6) return;
			zoom += 0.1;
			canvas.zoomToPoint(point,zoom);
			showZoomData();
		}
		//向下滑动
		else {
			if (zoom <= 0.4) {
				return;
			}
			zoom -= 0.1;
			canvas.zoomToPoint(point,zoom);
			showZoomData();
		}
	}
	else{
		return;
	}
}

//键盘按下事件
function keyDown(e) {
	var code = e.which;
	//alert(code);
	try{
		if (PageName == 'edit' && Edit == 1){
			switch(code)
			{
				case 17: e.preventDefault(); Connect(true); break;				//Ctrl辅助绘制连接线
				case 37: e.preventDefault(); moveTarget('left'); break;			//方向左
				case 38: e.preventDefault(); moveTarget('up'); break;			//方向上
				case 39: e.preventDefault(); moveTarget('right'); break;		//方向右
				case 40: e.preventDefault(); moveTarget('down'); break;			//方向下
				case 46: Delete(); break;										//Delete键删除元素
				case 82: RefreshPage(); break;									//R建刷新
				case 90: if (e.ctrlKey) {
					revocationInfo();
				}; break;											//Ctrl + Z撤销
			}
		}

	}
	catch(e){
		alert(e);
	}
}

//键盘抬起事件
function keyUp(e) {
	if (PageName == 'edit') {
		Connect(false);
	}
}

//移动节点（键盘控制）
function moveTarget(direction) {
	'use strict';
	var target = canvas.getActiveObject();						//获取当前活动节点
	var x = GetPointFromObj(target, 'LT')[0];					//取其当前左上角原点坐标
	var y = GetPointFromObj(target, 'LT')[1];
	if (direction == 'left') {											//判断方向
		if (x <= 0) return;												//越界中断
		else{
			var point = new fabric.Point(x - 10,y);				//定义新位置标定点
			target.setPositionByOrigin(point,'left','top');		//移动
			arrangeTarget(target);										//贴附到指定网格
			canvas.renderAll();
			reDrawConnector(target);
			freshCanvas();
		}
	}
	else if (direction == 'up') {
		if (y <= 0) return;
		else {
			var point = new fabric.Point(x, y - 10);
			target.setPositionByOrigin(point, 'left', 'top');
			arrangeTarget(target);
			canvas.renderAll();
			reDrawConnector(target);
			freshCanvas();
		}
	}
	else if (direction == 'right') {
		if (x >= 2900) return;
		else {
			var point = new fabric.Point(x + 10, y);
			target.setPositionByOrigin(point, 'left', 'top');
			arrangeTarget(target);
			canvas.renderAll();
			reDrawConnector(target);
			freshCanvas();
		}
	}
	else if(direction == 'down') {
		if (y >= 2900) return;
		else {
			var point = new fabric.Point(x, y + 10);
			target.setPositionByOrigin(point, 'left', 'top');
			arrangeTarget(target);
			canvas.renderAll();
			reDrawConnector(target);
			freshCanvas();
		}
	}
}






/*-------------------------------------------------------连接线绘制、设置功能块-----------------------------------------*/
//绘制动态引导线
function drawProcessLine(startpoint,endpoint) {
	'use strict';
	processline = new fabric.Line([startpoint.x, startpoint.y, endpoint.x, endpoint.y], {
		stroke:'#999',
		strokeWidth:1.5,
		type:'process',
		opacity:0.5
	});
	canvas.add(processline);
}

//（跳板）获取元素中的指定点，返回对象
function getOPointFromObj(target, str){
	'use strict';
	var po = [];
	po = GetPointFromObj(target, str);
	return(new fabric.Point(po[0], po[1]));
}

//所有连接线可选状态
function setConnectorsSelectable(sig){
	'use strict';
	if (sig == false) {
		for (var i in connectors) {
			connectors[i].set({
				selectable:false
			});
		}
	}
	else if (sig == true) {
		for (var i in connectors) {
			connectors[i].set({
				selectable:true
			});
		}
	}
}

//绘制连接线方法
//method strokeConnector(array)
function strokeConnector(keypoints) {
	'use strict';
	var connectorlines = [];
	for (var i = 0; i < keypoints.length-1; i++) {
		connectorlines[i] = new fabric.Line([keypoints[i].x, keypoints[i].y, keypoints[i+1].x, keypoints[i+1].y],{
			stroke: 'black',
			strokeWidth: 1,
			lockMovementX:true,
			lockMovementY:true,
			lockScalingX:true,
			lockScalingY:true,
			lockRotation:true,
			strokeLineCap: 'round'
		});
	}
	var cap = makeVCap(keypoints[keypoints.length - 1]);
	connectorlines.push(cap);
	var connector = new fabric.Group(connectorlines);
	connector.set({
		hasBorders:false,
		hasControls:false,
		objType:'Connector',
		CoType:'结束-开始'
	});
	setConnectorClear(connector);
	return(connector);
}

//定义连接关键点
var KeyPoint = function(x, y, position) {
	'use strict';
	//关键点的坐标
	this.x = x;
	this.y = y;
	//关键点位置描述(str)
	this.position = position;
}

//计算两点的中点
//Obj getCenterPoint(obj,obj)
function getCenterPoint(point1,point2) {
	'use strict';
	var x;
	var y;
	var dx = Math.abs(point1.x - point2.x) / 2;
	var dy = Math.abs(point1.y - point2.y) / 2;
	x = Math.min(point1.x,point2.x) + dx;
	y = Math.min(point1.y,point2.y) + dy;
	return new KeyPoint(x,y,'');
}

//绘制连接线箭头
//method makeVCap(obj)
function makeVCap(point) {
	'use strict';
	var ang;
	//根据终点于元素位置设置箭头角度
	if (point.position == "L") {
		ang = 90;
	}
	if (point.position == "T") {
		ang = 180;
	}
	if (point.position == "R") {
		ang = 270;
	}
	if (point.position == "B") {
		ang = 0;
	}
	//定义箭头
	var vcap = new fabric.Triangle({
		height:7,
		width:10,
		fill:'black',
		angle:ang,
		originX:'center'
	});
	var po = new fabric.Point(point.x, point.y);
	vcap.setPositionByOrigin(po, 'center', 'top');
	return(vcap);
}


//根据获得起终点获得关键点
//array getKeyPoints(obj,obj)
function getKeyPoints(startpoint,endpoint){
	'use strict';
	var d = 10;								//起始点和元素的距离
	var keypoints = [];						//连接点集合
	keypoints[0] = startpoint;

	/*****起点在元素上方*****/
	if (startpoint.position == 'T') {
		var vs = new KeyPoint(startpoint.x,startpoint.y - d,'key');		//起点向量点
		keypoints[1] = vs;
		//终点在元素上方
		if (endpoint.position == 'T') {
			var ve = new KeyPoint(endpoint.x,endpoint.y - d,'key');		//终点向量点
			//终点在起点上方
			if (endpoint.y < startpoint.y) {
				keypoints[2] = new KeyPoint(keypoints[1].x, endpoint.y - d, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点下方
			else if (endpoint.y > startpoint.y) {
				keypoints[2] = new KeyPoint(endpoint.x, keypoints[0].y - d, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}

		}
		//终点在元素右方
		if (endpoint.position == 'R') {
			var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
			//终点在起点上方
			if (endpoint.y < startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					keypoints[2] = new KeyPoint(keypoints[0].x, endpoint.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				if (endpoint.x > startpoint.x) {
					var cy = getCenterPoint(vs,ve).y;
					keypoints[2] = new KeyPoint(vs.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点和起点同一水平
				if (endpoint.x == startpoint.x) {
					keypoints[2] = ve;
					keypoints[3] = endpoint;
					return(keypoints);
				}
			}
			//终点在起点下方
			else if (endpoint.y > startpoint.y) {
				//终点在起点右边
				if (endpoint.x > startpoint.x) {
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					var cx = getCenterPoint(vs,ve).x;
					keypoints[2] = new KeyPoint(cx, vs.y, 'key');
					keypoints[3] = new KeyPoint(cx, ve.y, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点和起点垂直相同
				if (endpoint.x = startpoint.x) {
					keypoints[2] = ve;
					keypoints[3] = endpoint;
					return(keypoints);
				}
			} else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素下方
		else if (endpoint.position == 'B') {
			var ve = new KeyPoint(endpoint.x, endpoint.y + d);
			//终点在起点上方
			if (endpoint.y < startpoint.y) {
				var cy = getCenterPoint(startpoint,endpoint).y;
				keypoints[2] = new KeyPoint(vs.x, cy, 'key');
				keypoints[3] = new KeyPoint(ve.x, cy, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			//终点在起点下面
			else if (endpoint.y > startpoint.y) {
				var cx = getCenterPoint(vs,ve).x;
				keypoints[2] = new KeyPoint(cx, vs.y, 'key');
				keypoints[3] = new KeyPoint(cx, ve.y, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素左边
		else if (endpoint.position == 'L') {
			var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
			//终点在起点上边
			if (endpoint.y < startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					var cy = getCenterPoint(vs,ve).y;
					keypoints[2] = new KeyPoint(startpoint.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				else if (endpoint.x > startpoint.x) {
					keypoints[2] = new KeyPoint(startpoint.x, endpoint.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点和起点在同一垂直线上
				else{
					keypoints[2] = ve;
					keypoints[3] = endpoint;
					return(keypoints);
				}
			}
			//终点在起点下边
			if (endpoint.y > startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				else if (endpoint.x > startpoint.x) {
					var cx = getCenterPoint(vs,ve).x;
					keypoints[2] = new KeyPoint(cx, vs.y, 'key');
					keypoints[3] = new KeyPoint(cx, endpoint.y, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				else{
					keypoints[2] = ve;
					keypoints[3] = endpoint;
					return(keypoints);
				}
			}
		}
	}

	/*****起点在元素右边*****/
	if (startpoint.position == "R") {
		var vs = new KeyPoint(startpoint.x + d, startpoint.y, 'key');
		keypoints[1] = vs;
		//终点在元素上边
		if (endpoint.position == "T") {
			var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
			//终点在起点上方
			if (endpoint.y < startpoint.y) {
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点下方
			else if (endpoint.y > startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					var cy = getCenterPoint(vs,ve).y;
					keypoints[2] = new KeyPoint(vs.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				if(endpoint.x > startpoint.x){
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素右边
		if(endpoint.position == "R"){
			var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
			//终点在起点右边
			if(endpoint.x > startpoint.x){
				keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点左边
			else if(endpoint.x < startpoint.x){
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素下边
		if(endpoint.position == "B"){
			var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
			//终点在起点下方
			if(endpoint.y > startpoint.y){
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点上方
			else if(endpoint.y < startpoint.y){
				//终点在起点左边
				if(endpoint.x < startpoint.x){
					var cy = getCenterPoint(vs, endpoint).y;
					keypoints[2] = new KeyPoint(vs.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				if(endpoint.x > startpoint.x){
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素左边
		if(endpoint.position == "L"){
			var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
			//终点在起点左边
			if(endpoint.x < startpoint.x){
				var cy = getCenterPoint(vs,ve).y;
				keypoints[2] = new KeyPoint(vs.x, cy, 'key');
				keypoints[3] = new KeyPoint(ve.x, cy, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			//终点在起点右边
			else if(endpoint.x > startpoint.x){
				var cx = getCenterPoint(vs,ve).x;
				keypoints[2] = new KeyPoint(cx, vs.y, 'key');
				keypoints[3] = new KeyPoint(cx, ve.y, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
	}
	/*****起点在元素下端*****/
	if (startpoint.position == "B") {
		var vs = new KeyPoint(startpoint.x, startpoint.y + d, 'key');
		keypoints[1] = vs;
		//终点在元素上端
		if (endpoint.position == "T") {
			var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
			//终点在起点上面
			if (endpoint.y < startpoint.y) {
				var cx = getCenterPoint(vs,ve).x;
				keypoints[2] = new KeyPoint(cx, vs.y, 'key');
				keypoints[3] = new KeyPoint(cx, ve.y, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			//终点在起点下面
			else if (endpoint.y > startpoint.y) {
				var cy = getCenterPoint(vs,ve).y;
				keypoints[2] = new KeyPoint(vs.x, cy, 'key');
				keypoints[3] = new KeyPoint(ve.x, cy, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素右端
		if (endpoint.position == "R") {
			var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
			//终点在起点右边
			if (endpoint.x > startpoint.x) {
				keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点左边
			else if (endpoint.x < startpoint.x) {
				//终点在起点上边
				if (endpoint.y < startpoint.y) {
					var cx = getCenterPoint(vs, endpoint).x;
					keypoints[2] = new KeyPoint(cx, vs.y, 'key');
					keypoints[3] = new KeyPoint(cx, ve.y, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点在起点下边
				if (endpoint.y > startpoint.y) {
					keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
			}
			else{
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素下端
		if (endpoint.position == "B") {
			var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
			//终点在起点上面
			if (endpoint.y < startpoint.y) {
				keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点下面
			else if (endpoint.y > startpoint.y) {
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素左端
		if (endpoint.position == "L") {
			var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
			//终点在起点左边
			if (endpoint.x < startpoint.x) {
				keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点右边
			else if (endpoint.x > startpoint.x) {
				//终点在起点上边
				if (endpoint.y < startpoint.y) {
					var cx = getCenterPoint(vs, endpoint).x;
					keypoints[2] = new KeyPoint(cx, vs.y, 'key');
					keypoints[3] = new KeyPoint(cx, ve.y, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
				//终点在起点下边
				if (endpoint.y > startpoint.y) {
					keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
	}
	/*****起点在元素左边*****/
	if(startpoint.position == "L"){
		var vs = new KeyPoint(startpoint.x - d, startpoint.y, 'key');
		keypoints[1] = vs;
		//终点在元素上边
		if (endpoint.position == "T") {
			var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
			//终点在起点上边
			if (endpoint.y < startpoint.y) {
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点下边
			else if (endpoint.y > startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				if (endpoint.x > startpoint.x) {
					var cy = getCenterPoint(vs, endpoint).y;
					keypoints[2] = new KeyPoint(vs.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素右边
		if (endpoint.position == "R") {
			var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
			//终点在起点左边
			if (endpoint.x < startpoint.x) {
				var cx = getCenterPoint(vs, ve).x;
				keypoints[2] = new KeyPoint(cx, vs.y, 'key');
				keypoints[3] = new KeyPoint(cx, ve.y, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			//终点在起点右边
			else if (endpoint.x > startpoint.x) {
				var cy = getCenterPoint(vs, ve).y;
				keypoints[2] = new KeyPoint(vs.x, cy, 'key');
				keypoints[3] = new KeyPoint(ve.x, cy, 'key');
				keypoints[4] = ve;
				keypoints[5] = endpoint;
				return(keypoints);
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素下边
		if (endpoint.position == "B") {
			var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
			//终点在起点下边
			if (endpoint.y > startpoint.y) {
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点上边
			else if (endpoint.y < startpoint.y) {
				//终点在起点左边
				if (endpoint.x < startpoint.x) {
					keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
					keypoints[3] = ve;
					keypoints[4] = endpoint;
					return(keypoints);
				}
				//终点在起点右边
				if (endpoint.x > startpoint.x) {
					var cy = getCenterPoint(startpoint, endpoint, 'key').y;
					keypoints[2] = new KeyPoint(vs.x, cy, 'key');
					keypoints[3] = new KeyPoint(ve.x, cy, 'key');
					keypoints[4] = ve;
					keypoints[5] = endpoint;
					return(keypoints);
				}
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
		//终点在元素左边
		if (endpoint.position == "L") {
			var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
			//终点在起点左边
			if (endpoint.x < startpoint.x) {
				keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			//终点在起点右边
			if (endpoint.x > startpoint.x) {
				keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
				keypoints[3] = ve;
				keypoints[4] = endpoint;
				return(keypoints);
			}
			else {
				keypoints[2] = ve;
				keypoints[3] = endpoint;
				return(keypoints);
			}
		}
	}
}

//重新绘制连接线
//method reDrawConnector(object)
function reDrawConnector(obj) {
	'use strict';
	for (var i in connectors) {
		var CoType = connectors[i].CoType;
		//移动连接线起点的元素时
		if (connectors[i].headId == obj.id) {
			//重获起点坐标
			var po = [];
			po = GetPointFromObj(obj, connectors[i].startPo);
			var startpoint = new KeyPoint(po[0], po[1], connectors[i].startPo);
			//取得终点元素，指定终点坐标
			var target = getObjectById(connectors[i].endId);
			var poe = [];
			poe = GetPointFromObj(target, connectors[i].endPo);
			var endpoint = new KeyPoint(poe[0], poe[1], connectors[i].endPo);

			var keypos = [];
			keypos = getKeyPoints(startpoint,endpoint);
			//删除原连接线，增加新连接线
			canvas.remove(connectors[i]);
			connectors.splice(i,1);
			var ve = strokeConnector(keypos);
			ve.set({
				headId:obj.id,
				endId:target.id,
				startPo:startpoint.position,
				endPo:endpoint.position,
				CoType:CoType
			});
			setConnectorClear(ve);
			canvas.add(ve);
			connectors.push(ve);
			canvas.renderAll();
			canvas.sendToBack(ve);
			reLoadTagsCollection();										//刷新节点集合选项
		}
		//当移动连接线终点的元素时
		else if (connectors[i].endId == obj.id) {
			//获取终点坐标
			var poe = [];
			poe = GetPointFromObj(obj, connectors[i].endPo);
			var endpoint = new KeyPoint(poe[0], poe[1], connectors[i].endPo);
			//取得起点连接元素，获取起点坐标
			var target = getObjectById(connectors[i].headId);
			var po = [];
			po = GetPointFromObj(target, connectors[i].startPo);
			var startpoint = new KeyPoint(po[0], po[1], connectors[i].startPo);
			var keypos = [];
			keypos = getKeyPoints(startpoint,endpoint);
			//删除当前，绘制最新
			canvas.remove(connectors[i]);
			connectors.splice(i,1);
			var ve = strokeConnector(keypos);
			ve.set({
				headId:target.id,
				endId:obj.id,
				startPo:startpoint.position,
				endPo:endpoint.position,
				CoType:CoType
			});
			canvas.add(ve);
			setConnectorClear(ve);
			connectors.push(ve);
			canvas.renderAll();
			canvas.sendToBack(ve);
			reLoadTagsCollection();										//刷新节点集合选项
		}
	}
}

//根据id获取查找元素
//obj getObjectById(num)
function getObjectById(id) {
	'use strict'
	var objGet = false;
	for (var i in objs) {
		if (objs[i].id == id) {
			objGet = objs[i];
		}
	}
	return objGet;
}


/*---------------------------------------------------------------------------------------------------------------------*/




/*------------------------------------------------连接线辅助提示点功能块-----------------------------------------------*/
//判断并返回鼠标下的元素
//Obj getObjectUnderMouse(obj)
function getObjectUnderMouse(point) {
	'use strict';
	if (objs.length > 0) {
		for (var i in objs) {
			if (PointInObject(point.x, point.y, objs[i])) {
				return(objs[i]);
			}
		}
	}
}

//初始化连接提示点
function initHelpPoint() {
	'use strict';
	helppoint = new fabric.Circle({
		opacity:0.5,
		left:20,
		top:20,
		radius:9,
		stroke:'#999',
		strokeWidth:5,
		selectable:false,
		id:'cp',
		visible:false
	});
	canvas.add(helppoint);
}

//显示连接提示点
function showConnectHelpPoint(point) {
	'use strict';
	//定义提示点样式
	var target = getObjectUnderMouse(point);						//获取当前鼠标坐标下的对象
	if(target){
		var po = [];
		po = whitchPointInObject([point.x, point.y], target);			//获取当前鼠标点位于元素的哪个连接点
		var str = whitchPointInObjectStr([point.x, point.y], target);	//获取当前鼠标坐标位于元素的那个连接点描述

		canvas.bringToFront(helppoint);								//将提示点放在最前端
		if(str == 'L'){
			var p = new fabric.Point(po[0] + 5, po[1]);
		}
		if(str == 'T'){
			var p = new fabric.Point(po[0], po[1] + 5);
		}
		if(str == 'R'){
			var p = new fabric.Point(po[0] - 5, po[1]);
		}
		if(str == 'B'){
			var p = new fabric.Point(po[0], po[1] - 5);
		}
		helppoint.setPositionByOrigin(p, 'center', 'center');		//将提示点贴在该连接点上
		helppoint.setVisible(true);									//提示点显示
	}
	else{
		return;
	}
}

//隐藏连接提示点
function hideHelpPoint() {
	'use strict';
	helppoint.setVisible(false);
	helppoint.sendToBack();
}
/*---------------------------------------------------------------------------------------------------------------------*/




/*---------------------------------------------读取、生成工作流配置功能块------------------------------------------------*/
//根据名称获取Url中某个参数的值
function GetUrlParam(pname) {
	var reg = new RegExp("(^|&)" + pname + "=([^&]*)(&|$)");
	var r = window.location.search.substr(1).match(reg);
	if (r != null) return decodeURI(r[2]);
	return null;
}

//寻找节点上下流程节点获取id
//Array findPreOrNextObj(String,Number)	str = pre || next
function findPreOrNextObj(str, id) {
	'use strict';
	//查询获取后置节点id
	if(str == 'next'){
		var nextids = [];		//存储后置节点的id
		for (var i in connectors) {
			if (connectors[i].headId == id) {
				nextids.push(connectors[i].endId);
			}
		}
		return(nextids);
	}
	//查询获取前置节点id
	if (str == 'pre') {
		var preids = [];
		for (var i in connectors) {
			if (connectors[i].endId == id) {
				preids.push(connectors[i].headId);
			}
		}
		return(preids);
	}
}

//获取元素前后连接线
//Array getConsForObj(string, num)
function getConsForObj(str, id){
	'use strict';
	var cons = [];
	//获取前置连接线
	if (str == 'pre') {
		for (var i in connectors){
			if (connectors[i].endId == id) {
				cons.push(connectors[i]);
			}
		}
		return(cons);
	}
	//获取后置连接线
	if (str == 'next') {
		for (var i in connectors) {
			if (connectors[i].headId == id) {
				cons.push(connectors[i]);
			}
		}
		return(cons);
	}
}

//查询该元素的前后连接点位置信息
function getConPoById(str, id){
	'use strict';
	var cons = [];
	cons = getConsForObj(str, id);		//获取指定连接线
	//获取前置连接点位置信息
	if (str == 'pre') {
		var prepos = [];
		for (var i in cons) {
			prepos.push(cons[i].endPo);
		}
		return(prepos);
	}
	//获取后置连接点位置信息
	if (str == 'next') {
		var endpos = [];
		for (var i in cons) {
			endpos.push(cons[i].startPo);
		}
		return(endpos);
	}
}

//从服务器获取配置XML，并解析
function getXMLFromServer(){
	'use strict';
	var datas = {
		"id":workFlowId,
	};
	ibcpAjax.Select(workFlowCheckUrl,datas,false,function(result){
		txt = result.data.resource;
		if(txt == ""){
			return;
		}else{
			loadConfigInfo(txt);
		}
	});
}

//解析XML内容，生成工作流
function loadConfigInfo(text) {
	'use strict';
	try{
		var xmlDoc = loadXMLString(text);
		var tags = xmlDoc.getElementsByTagName('targets')[0].childNodes;	//选取所有节点元素配置
		if (tags.length == 0) {
			return;
		}
		for (var i = 0; i < tags.length; i++) {
			//Start节点
			if (tags[i].getAttribute('objType') == 'Start') {								//判断节点类型
				Start();																	//绘制对应的节点种类
				var target = objs[objs.length - 1];											//找到当前绘制的节点
				//对应到配置中的位置信息
				var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
				//设置节点属性
				target.set({
					id:tags[i].getAttribute('id'),
					stepname:tags[i].getAttribute('stepname'),
				});
				target.setPositionByOrigin(po, 'center', 'center');
				//设置节点文字内容
				var Text = findTextInGroup(target);
				Text.set({
					text:target.stepname,
					fontSize:FontSize
				});
				centerTextForTarget(target);
				canvas.renderAll();
			}
			//Task节点
			if (tags[i].getAttribute('objType') == 'Task') {
				drawRectangleCmd();
				var target = objs[objs.length - 1];
				var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
				target.set({
					id:tags[i].getAttribute('id'),
					number:tags[i].getAttribute('number'),
					stepId:tags[i].getAttribute('stepId'),
					stepname:tags[i].getAttribute('stepname'),
					version:tags[i].getAttribute('version'),
					stepCode:tags[i].getAttribute('stepCode')
				});
				target.setPositionByOrigin(po, 'center', 'center');
				var Text = findTextInGroup(target);
				Text.set({
					text:target.number + "-" + target.stepname,
					fontSize:FontSize
				});
				centerTextForTarget(target);
				canvas.renderAll();
			}
			//Gate节点
			if (tags[i].getAttribute('objType') == 'Gate') {
				drawDiamondCmd();
				var target = objs[objs.length - 1];
				var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
				target.set({
					id:tags[i].getAttribute('id'),
					formula:tags[i].getAttribute('formula')
				});
				target.setPositionByOrigin(po, 'center', 'center');
				canvas.renderAll();
			}
			//End节点
			if (tags[i].getAttribute('objType') == 'End') {
				End();
				var target = objs[objs.length - 1];
				var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
				target.set({
					id:tags[i].getAttribute('id'),
					stepNamne:tags[i].getAttribute('stepname'),
				});
				target.setPositionByOrigin(po, 'center', 'center');
				var Text = findTextInGroup(target);
				Text.set({
					text:tags[i].getAttribute('stepname'),
					fontSize:FontSize
				});
				centerTextForTarget(target);
				canvas.renderAll();
			}
		}
		//强制刷新画布
		freshCanvas();
		//连接线读取生成
		var cons = xmlDoc.getElementsByTagName('connectors')[0].childNodes;
		for (var i = 0; i < cons.length; i++) {
			if (cons[i].getAttribute('objType') == 'Connector') {								//连接线线种选择
				var pretarget = getObjectById(cons[i].getAttribute('headId'));		//上一个连接节点
				var nexttarget = getObjectById(cons[i].getAttribute('endId'));		//下一个连接节点
				var po = [];
				po = GetPointFromObj(pretarget,cons[i].getAttribute('startPo'));	//上一个连接点
				var startpoint = new KeyPoint(po[0], po[1], cons[i].getAttribute('startPo'));
				var epo = [];
				epo = GetPointFromObj(nexttarget, cons[i].getAttribute('endPo'));	//下一个连接点
				var endpoint = new KeyPoint(po[0], po[1], cons[i].getAttribute('startPo'));
				var keypoints = [];
				keypoints = getKeyPoints(startpoint,endpoint);
				var connector = strokeConnector(keypoints);
				connector.set({
					startPo:cons[i].getAttribute('startPo'),	//连接线起点坐标相对元素位置
					endPo:cons[i].getAttribute('endPo'),		//连接线终点坐标相对元素位置
					headId:cons[i].getAttribute('headId'),				//连接线起点连接元素id
					endId:cons[i].getAttribute('endId'),						//连接线终点连接元素id
					objType:cons[i].getAttribute('objType'),						//对象种类
					CoType:cons[i].getAttribute('CoType')							//连接线种类
				});
				canvas.add(connector);
				connectors.push(connector);
			}
		}
		//重绘所有连接线
		for (var i in objs) {
			reDrawConnector(objs[i]);
		}
		//将Id指向当前最大
		Id = getMaxId() + 1;
		configInfo();		//记录当前配置
	}
	catch(e) {
		ibcpLayer.ShowMsg('解析失败：程序数据格式错误！');
	}
}

//XML字符串解析
function loadXMLString(text) {
		var parser = new DOMParser();
		xmlDoc = parser.parseFromString(text, "text/xml");
	return xmlDoc;
}

//将XML DOM转化成字符串
function parseXML(doc){
	'use strict';
	var oSerializer = new XMLSerializer();
	return oSerializer.serializeToString(doc, 'text/xml');
}

//记录配置信息
function configInfo(save){
	'use strict';
	//loadXMLString(txt);
	txt = '<?xml version="1.0" encoding="utf-8"?>';
	txt = txt + '<ibatch>';
	txt = txt + '<targets>';
	//节点部分
	for (var i in objs){
		var id = objs[i].id,                        //节点id
			number = objs[i].number,				//节点序号
			objType = objs[i].objType,              //节点类型
			locx = GetPointFromObj(objs[i],'C')[0], //节点X坐标
			locy = GetPointFromObj(objs[i],'C')[1], //节点Y坐标
			stepId = objs[i].stepId ? objs[i].stepId : null,                	//节点实体id（程序id）
			stepname = objs[i].stepname,            							//节点实体名称（程序名称）
			stepCode = objs[i].stepCode ? objs[i].stepCode : null,            //节点实体代码（程序代码）
			version = objs[i].version ? objs[i].version : null,              //节点实体版本（程序版本）
			formula = objs[i].formula ? objs[i].formula : null,       //判断项公式
			workId = objs[i].workId ? objs[i].workId : null,            //工位（组）id
			workCode = objs[i].workCode ? objs[i].workCode : null,    //工位（组）代码
			workName = objs[i].workName ? objs[i].workName : null,    //工位（组）名称
			workType = objs[i].workType ? objs[i].workType : null;		//工位种类

		txt = txt + '<target id="' + id + '" number="' + number + '" objType="' + objType + '" locx="' + locx + '" locy="' + locy + '" stepId="' + stepId + '" stepname="' + stepname + '" stepCode="' + stepCode + '" version="' + version +'" formula="' + formula + '" workId="' + workId + '" workCode="' + workCode + '" workName="' + workName + '" workType="' + workType + '"></target>';
	}
	txt = txt + '</targets>';
	txt = txt + '<connectors>';
	//连接线部分
	for (var i in connectors){
		txt = txt + '<connector objType="' + connectors[i].objType + '" CoType="' + connectors[i].CoType + '" headId="' + connectors[i].headId.toString() + '" endId="' + connectors[i].endId.toString() + '" startPo="' + connectors[i].startPo + '" endPo="' + connectors[i].endPo + '" ></connector>';
	}
	txt = txt + '</connectors>';
	txt = txt + '</ibatch>';

	if(save){
		//检查数据是否合法
		var propotyCheck = ibcpFlowCheck.errorCheck();
		if(propotyCheck == false){
			ibcpLayer.ShowMsg("请完善流程图信息！");
			return;
		} 

		signPath = '../../Public/';
		CallSign(100, function(sid) {
			var datas = {
				"id":workFlowId,
				"resource":txt,
				"sid":sid
			}
			ibcpAjax.Update(workFlowEditUrl,datas,false,function(result){
				SignCancel();
				ibcpLayer.ShowOK("保存成功！");
				$('#SignDiv').html("");
				window.parent.LoadproPic(workFlowId);
			});
		});
	}
}
/*--------------------------------------------------------------------------------------------------------------------*/




/*---------------------------------------------画面格式整理功能块-------------------------------------------------------*/
//将当前节点贴附到网格焦点上
function arrangeTarget(target) {
	'use strict';
	var po = [];
	po = GetPointFromObj(target,'C');
	var x = searchNearNum(po[0],5);
	var y = searchNearNum(po[1],5);
	var point = new fabric.Point(x,y);
	target.setPositionByOrigin(point, 'center', 'center');
	canvas.renderAll();
	reDrawConnector(target);
	freshCanvas();
}

//判断数字和某数的倍数相近
function searchNearNum(num, stdnum){
	'use strict';
	var residue = num % stdnum;
	var quotient = parseInt(num / stdnum);
	if (residue < (stdnum / 2)) {
		return(num - residue);
	}
	else {
		return((quotient + 1) * stdnum);
	}
}

//刷新节点
function freshCanvas() {
	'use strict';
	//通过缩放刷新节点位置
	var point = new fabric.Point(0, 0);
	canvas.zoomToPoint(point, zoom - 0.1);
	canvas.zoomToPoint(point, zoom);
}

//获取鼠标坐标
function getMousePos(event) {
	var e = event || window.event;
	return {
		'x':e.clientX,
		'y':clientY
	}
}

//显示缩放比例
function showZoomData() {
	'use strict';
	var $box = $('#zoombox');
	var $show = $('#zoomshow');
	$show.html(parseInt(zoom * 100) + "%");			//将缩放倍数转换成百分比形式
	//计算工作区中心
	var x = ($('#canvasbox').width() - $box.width()) / 2;
	var y = ($('#canvasbox').height() - $box.height()) / 2;
	$box.attr('style','display:""');
	$box.css({
		left:x,
		top:y
	});
	//两秒消失
	window.setTimeout( function() {
		$box.attr('style','display:none')
	}, 2000);
}

//设置按钮选中状态
function setButtonSelected(btn, stage) {
	'use strict';
	if (stage == true) {
		btn.removeClass('toolBtn');
		btn.addClass('down');
	}
	if (stage == false) {
		btn.addClass('toolBtn');
		btn.removeClass('down');
	}
}

//清除属性面板内容
function clearInstallPage() {
	'use strict';
	$('input[wftype]').each(function(){
		$(this).val('');
		$(this).attr('readonly', true);
	});
	$('textarea[wftype]').each(function(){
		$(this).val('');
		$(this).attr('readonly', true);
	});
	$('select[wftype]').each(function(){
		$(this).attr('disabled', true);
	});
	$('button[wftype]').each(function(){
		$(this).attr('disabled', true);
	});
}

//页面最大化
function Max(){
	'use strict';
	var index = parent.layer.getFrameIndex(window.name);
	parent.layer.iframeAuto(index);
}


//将节点中的文字居中对齐
function centerTextForTarget(target){
	'use strict';
	var Text = findTextInGroup(target);
	var Point = new fabric.Point(0,0);
	Text.setPositionByOrigin(Point, "center", "center");
	canvas.renderAll();
}
/*---------------------------------------------------------------------------------------------------------------------*/




/*--------------------------------------弹出层功能块------------------------------------------------------------*/
//弹出选择节点画面
function stepSelectPage(title, url, width, height){
	'use strict';
	var $page = $('<div id="Step_Select_Box" style="position:absolute;"></div>');
	var $cont = $('<div id="Step_Select_Page" style="position:absolute;border-radius:5px;"><div style="padding-left:10px;padding-top:5px;margin:0;background-color:#F8F8F8"><h4>'+ title + '</h4></div><div id="Step_Select_Page_Content" style="width:100%;"></div></div>');
	this.show = function(){
		$('body').after($page);
		$('body').after($cont);
		var $width = $(window).width();
		var $height = $(window).height();
		var $left = ($width - width) / 2;
		var $top = ($height - height) / 2;

		$('#Step_Select_Box').css('width', $(window).width());
		$('#Step_Select_Box').css('height', $(window).height());
		$('#Step_Select_Page').css('width', width);
		$('#Step_Select_Page').css('height', height);
		$('#Step_Select_Page').css('left', $left);
		$('#Step_Select_Page').css('top', $top);
		$('#Step_Select_Page_Content').load(url,null);
		$('#Step_Select_Page').css('opacity', 1);
		$('#Step_Select_Page').css('z-index', 1001);

		$(window).resize(function(){
			$('#Step_Select_Box').css('width', $(window).width());
			$('#Step_Select_Box').css('height', $(window).height());
			$('#Step_Select_Page').css('left', ($(window).width() - width) / 2);
			$('#Step_Select_Page').css('top', ($(window).height() - height) / 2);
		});

		$('#Step_Select_Close_Btn').on('click',function(){
			$page.remove();
			$cont.remove();
		});
	};

	this.close = function(){
		$page.remove();
		$cont.remove();
	}
}
/*-----------------------------------------------------------------------------------------------------------*/



/*---------------------------------------------撤销功能块-------------------------------------------------------*/
//时时记录状态信息
function configOnTime() {
	'use strict';
	if (revocation == false) {
		configInfo();
		if (configStore.length > 20) {
			configStore.splice(0,1);
		}
		configStore.push(txt);
	}else {
		return;
	}
}

//撤销
function revocationInfo() {
	'use strict';
	if (configStore.length >= 2) {
		revocation = true;
		configStore.splice(configStore.length - 1, 1);
		var text = configStore[configStore.length - 1];
		text = text.replace(/[\n]/ig, '');															//格式化XML字符串
		ClearPage();																				//清空当前工作台内容
		loadConfigInfo(text);
		revocation = false;
		Id = getMaxId() + 1;																		//将id指针指向当前最大后一位
	}else {
		configStore = [];
		revocation = false;
		return;
	}
}

//获取当前最大id
function getMaxId() {
	'use strict';
	var maxId = 0;
	for(var i in objs){
		if(objs[i].id < 99999999){
			maxId = Math.max(maxId, objs[i].id);
		}
	}
	return maxId;
}
/*--------------------------------------------------------------------------------------------------------------*/


/*----------------------------------------查看流程功能块----------------------------------------------------------*/
/*------------------------These functions server for WorkFlowCheck.html------------------------------------------*/
//固定所有节点不可拖动和缩放
function fixAllTarget(){
	'use strict';
	for(var i in objs){
		objs[i].set({
			lockMovementX:true,
			lockMovementY:true,
			lockScalingX:true,
			lockScalingY:true
		});
	}
}
/*----------------------------------------------------------------------------------------------------------------*/




/*-----------------------------------------------------步骤编辑功能块--------------------------------------------------*/
//显示步骤选择画面
function showStepSelect(){
	'use strict';
	var url = "ProgramStepCheck.html";
	stepAddDivIndex = ibcpLayer.ShowDiv(url, '输入步骤信息', '500px', '400px',function(){
		initStepAdd();
	});
}

//步骤选择画面事件
function initStepAdd(){
	'use strict';
	$('#PSCancel').on('click', function(){
		ibcpLayer.Close(stepAddDivIndex);
	});
}

//公式提交按钮功能
function formulaSubmit(){
	'use strict';
	var target = getObjectById(ActiveId);
	var cont = document.getElementById('WF_Formula').value;
	if (target.objType == "Gate") {
		target.set({
			formula:cont
		});
	}
}

//根据点击元素类型设置属性面板状态
function setEditStateByType(type){
	'use strict';
	//只针对开始和结束显示信息
	if (type == "Start" || "End"){
		$('[bcsgrp]').css('display','none');
		$('[bcsgrp="Info-Task"]').css('display','inline');
	}
	//只针对步骤开放选择步骤操作
	if (type == "Task") {
		$('#WF_Edit').removeAttr('disabled');
		$('tr[bcsgrp]').css('display','none');
		$('tr[bcsgrp="Info-Task"]').css('display','inline');
	}

	//只针对连接线开放选择链接种类操作
	if (type == "Connector"){
		$('tr[bcsgrp]').css('display','none');
		$('tr[bcsgrp="Info-Connector"]').css('display','inline');
		if(PageName == "edit"){
			$('#WF_CoType').removeAttr('disabled');
		}
	}

	//只针对判断项开放公式输入信息和程序选择
	if (type == "Gate") {
		$('tr[bcsgrp]').css('display','none');
		$('tr[bcsgrp="Info-Gate"]').css('display','inline');
		if(PageName == "edit"){
			$('#WF_Formula').removeAttr('readonly');
			$('#WF_FormulaSubmit').removeAttr('disabled');
		}
	}

	if (type == "clear") {
		$('tr[bcsgrp]').css('display','none');
		$('#WF_Edit').attr('disabled', true);
		$('#WF_CoType').attr('disabled', true);
		$('#WF_Formula').attr('readonly', true);
	}
}

//显示属性面板信息
//method showInfo(obj)
function showInfo(target) {
	'use strict';
	try{
		//开始节点信息
		if(target.id == 0){
			$('#WF_Name').val(target.stepname);						//显示开始名称
		}
		//结束节点信息
		else if(target.id == 99999999){
			$('#WF_Name').val(target.stepname);						//显示结束名称
		}
		//步骤项信息
		else if(target.objType == "Task"){
			$('#WF_Code').val(target.stepCode);							//读取节点代码
			$('#WF_Name').val(target.stepname);						//读取节点名称
			$('#WF_Version').val(target.version);					//读取步骤版本
		}
		//判断项信息
		else if(target.objType == "Gate"){
			$('#WF_Formula').val(target.formula);					//读取判断公式
		}
		//连接线信息
		else if(target.objType == "Connector"){
			if(target.CoType == "开始-开始"){						//读取连接线链接类型
				$("#WF_CoType").val(0);
			}else if(target.CoType == "结束-开始"){
				$("#WF_CoType").val(1);
			}
			var headtarget = getObjectById(target.headId);			//获取前连接点
			var endtarget = getObjectById(target.endId);			//获取后连接点
			$('#WF_CoStart').val((headtarget.objType == "Gate") ? "判断项" : headtarget.stepname);				//显示前连接点
			$('#WF_CoEnd').val((endtarget.objType == "Gate") ? "判断项" : endtarget.stepname);					//显示后连接点
		}else {
			return;
		}
		setEditStateByType(target.objType);

	}catch(e){
		alert(e);
	}
}


//设置连接线种类
function selectCoType(id){
	'use strict';
	var target = ActiveConnector;
	if (target.objType == 'Connector') {
		target.CoType = $('#'+ id).find("option:selected").text();
		setConnectorClear(target);											//设置当前属性的连接线样式
		reLoadTagsCollection();												//刷新节点集合选项
	}else{
		return;
	}
}

//寻找Group中text
function findTextInGroup(target) {
	'use strict';
	for(var i = 0; i >= 0; i ++) {
		if (target.item(i).type == 'text') {
			return(target.item(i));
		}
	}
}

//将步骤选择列表中的信息填入当前选中元素中
function selectStepInfo(wfcode, wfname, wfversion, wfid, stepNumber){
	'use strict';
	if(wfcode == null || wfname == null || wfversion == null) return;
	var target = getObjectById(ActiveId);
	if (target.objType == 'Task') {
		target.set({
			number: stepNumber,
			stepCode: wfcode,
			stepname: wfname,
			version: wfversion,
			stepId: wfid
		});
		var Text = findTextInGroup(target);
		Text.set({
			text:stepNumber + "-" + wfname,
			fontSize:FontSize
		});
		centerTextForTarget(target);					//文字居中显示
		ibcpLayer.Close(stepAddDivIndex);				//关闭选择页面
	}
	reLoadTagsCollection();								//刷新节点集合选项
	showInfo(target);
}

//刷新节点集合中的信息
function reLoadTagsCollection(){
	'use strict';
	clearSelectOptions('Current_Target');
	getAllTagsForSelector();
	//getAllConnectorsOptions();
}

//将工作流所有节点写入节点集合中
function getAllTagsForSelector(){
	'use strict';
	var objList = [];
	for(var i in objs){
		if(objs[i].objType == 'Task'){
			objList.push([String(objs[i].stepCode) + "--" + objs[i].stepname, objs[i].id]);
		}
		if(objs[i].objType == 'Gate'){
			var ids = [];
			ids = findPreOrNextObj('pre', objs[i].id);						//获得上一个节点的id集合（这里为判断节点，入口应为一个）
			var preTag = getObjectById(ids[0]);								//根据id找到入口节点
			if(preTag)	objList.push([String(preTag.stepCode) + "--" + preTag.stepname + "【判断项】", objs[i].id]);
		}
	}
	var sObjList = objList.sort();
	for( var i in sObjList){
		insertOption('Current_Target', sObjList[i][1], sObjList[i][0]);
	}
}


//清空工作流集合下拉框
function clearAllOptions(selectId){
	'use strict';
	var selector = document.getElementById(selectId);
	for (var i = 0; i < selector.options.length; i++){
		selector.options[i].remove();
	}
}

//根据value删除指定选项
function delectAOption(selectId,value){
	'use strict';
	var selector = document.getElementById(selectId);
	for (var i = 0; i < selector.options.length; i++){
		if(selector.options[i].value == value){
			selector.options[i].remove();
		}
	}
}

//向select中添加一条option
function insertOption(selectId, value, text){
	'use strict';
	var select = document.getElementById(selectId);
	select.options.add(new Option(text, value));
}

//查找select中是否含有指定value
function checkValueInSelect(selectId, value){
	'use strict';
	var isExit = false;
	var select = document.getElementById(selectId);
	for (var i = 0;i < select.options.length; i++){
		if (select.options[i].value == target.id) {
			isExit = true;
			break;
		}
	}
	return isExit;
}

//根据value设置select当前选中值
function setSelectSelected(selectId, value){
	'use strict';
	var select = document.getElementById(selectId);
	for(var i = 0; i < select.options.length; i++){
		if(value == select.options[i].value){
			select.options[i].selected = true;
		}
	}
}

//清空当前元素展示
function currentTargetClear(){
	'use strict';
	$('#Current_Target').html("");
}

//清空select中的动态项
function clearSelectOptions(selectId){
	'use strict';
	var select = document.getElementById(selectId);
	select.innerHTML = "";
}

//显示当前选中节点在节点结合中的选项
function showCurrentTatgetSelect(object){
	'use strict';
	if(object.objType == 'Connector'){
		var val = String(object.headId) + "-" + String(object.endId);
		setSelectSelected('Current_Target', val)
	}
	if(object.objType == 'Start' || 'End' || 'Task' || 'Gate'){
		setSelectSelected('Current_Target', object.id)
	}
}

//获取select当前选中的value
function getCurrentOption(selectId){
	'use strict';
	var select = document.getElementById(selectId);
	for(var i = 0; i < select.options.length; i++){
		if(select.options[i].selected == true){
			return select.options[i].value;
		}
	}
}

//节点集合下拉框选择事件
function initCurrentTargetSelector(){
	'use strict';
	var select = document.getElementById('Current_Target');
	select.setAttribute('onfocus','fixEditor()');
	select.setAttribute('onblur','editEditor()');
	select.onchange = function(){
		var val = getCurrentOption('Current_Target');
		var target = getObjectById(val);
		if(target){
			clearInstallPage();
			showInfo(target);
			selectCleared();
			setObjectSelected(target);
		}
		else{
			for(var i in connectors){
				var ids = String(connectors[i].headId) + "-" + String(connectors[i].endId);
				if(ids == val){
					clearInstallPage();
					showInfo(connectors[i]);
					selectCleared();
					setConnectorSelected(connectors[i]);
				}
			}
		}
	}
}
//停止键盘监听
function fixEditor(){
	Edit = 0;
}
//允许键盘监听
function editEditor(){
	Edit = 1;
}

//模拟节点选中状态样式
function setSelectedTag(target){
	'use strict';
	if(target){
		setTargetSelected(target, 1);
	}

	if(target == null){
		for(var i in objs){
			setTargetSelected(objs[i], 2);
		}
		for(var i in connectors){
			setConnectorClear(connectors[i]);
		}
	}
	canvas.renderAll();
}


/*---------------------------------------------------------------------------------------------------------------------*/






/*---------------------------------------------检查、限制功能模块--------------------------------------------------------*/
/*通过类型检查是否存在元素，返回bool值，存在返回true*/
function checkUpTargetByType(type){
	'use strict';
	if (type == "Start") {
		if (getObjectById(0)) {
			return true;
		}else{
			return false
		}
	}
	if (type == "End") {
		if (getObjectById(99999999)) {
			return true
		}else{
			return false;
		}
	}
}

/*判断是否保存*/
function savedCheck(){
	'use strict';
	var precon;
	var datas = {
		"id":workFlowId,
	}
	ibcpAjax.Select(workFlowCheckUrl,datas,false,function(result){
		precon = result.data.resource;
	});
	configInfo(null);
	if (precon == txt) {
		return(false);					//不需要保存	
	}else{
		return(true);					//需要保存
	}
}


/*画面关闭事件*/
function initUnloadEvent(){
	'use strict';
	layer.confirm('系统检测到您最近的工作没有进行保存，是否在关闭前进行保存？', {
		title: '提示',
		zIndex: layer.zIndex,
		btn: ['保存', '关闭'],
		yes: function (index) {
			ConfigInfo();
		},
		btn2: function(index){
			var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
			parent.layer.close(index);
		}
	});
}

/*检查程序合法性*/
function checkWorkFlow(){
	'use strict';

}

/*根据指定属性查找元素*/
function getObjectByProp(prop, value){
	'use strict';
	var searchTargets = [];
	for(var i in objs){
		if(objs[i][prop] == value){
			searchTargets.push(objs[i]);
		}
	}
	return searchTargets;
}
/*----------------------------------------------------------------------------------------------------------------------*/








/*-------------------------------------------------元素样式改变功能块---------------------------------------------------*/
//设置节点选中样式
function setObjectSelected(target){
	'use strict';
	if(target.objType != "Connector"){
		target.set({
			opacity: 0.3
		});
	}
	canvas.renderAll();
	ActiveId = target.id;
}

//设置元素还原样式
function setObjectCleared(target){
	'use strict';
	target.set({
		opacity: 1
	});
	canvas.renderAll();
	ActiveId = null;
}

//设置连接线选中样式
function setConnectorSelected(connector){
	'use strict';
	connector.set({
		stroke: 'red'
	});
	canvas.renderAll();
	ActiveConnector = connector;
}

//设置连接线清除选择样式
function setConnectorClear(connector){
	'use strict';
	if(connector.CoType == "开始-开始"){
		connector.set({
			stroke: 'blue'
		});
	}else if(connector.CoType == "结束-开始"){
		connector.set({
			stroke: 'black'
		});
	}
	canvas.renderAll();
	ActiveConnector = null;
}


//清除选中状态
function selectCleared(){
	'use strict';
	for(var i in objs){
		setObjectCleared(objs[i]);
	}
	for(var i in connectors){
		setConnectorClear(connectors[i]);
	}
	canvas.renderAll();
}

/*----------------------------------------------------------------------------------------------------------------------*/
//**********************************
/*-----This area is for ready-----*/
//**********************************



//*********************************
/*-----This area is for test-----*/
//*********************************
//Test
function Test(){
	'use strict';
	try{
		var starttarget = getObjectById(0);
		var endtarget = getObjectById(1);
		var startpo = getOptimalConnection(starttarget, endtarget)[0];
		var endpo = getOptimalConnection(starttarget, endtarget)[1];
		var points = [];
		points = getKeyPoints(startpo,endpo);
		var connector = strokeConnector(points);
		connector.set({
			startPo:startpo.position,										//连接线起点坐标相对元素位置
			endPo:endpo.position,											//连接线终点坐标相对元素位置
			headId:starttarget.id,											//连接线起点连接元素id
			endId:endtarget.id												//连接线终点连接元素id
		});
		canvas.add(connector);												//绘制连接线
		connectors.push(connector);											//储存连接线
		canvas.sendToBack(connector);										//将连接线放在canvas堆栈最底层
		setConnectorsSelectable(false);
	}
	catch(e){
		alert(e);
	}
}






















	